using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Configuration;
using Microsoft.MediaCenter.UI;
using Microsoft.MediaCenter.Hosting;
using System.Xml.Serialization;
using System.IO;
using System.Threading;
using Level65.ClipShow;
using Level65.WMVHelper;
using System.Diagnostics;

namespace ClipShow
{

    public class ViewItem
    {
        public ViewItem()
        {
        }

        private int _myIndex = -1;

        public int MyIndex
        {
            get { return (_myIndex); }
            set { _myIndex = value; }
        }
    }
    public class MainCodeBehind : CoreUICodeBehind
    {
        private Choice _myChannelSource;
        private Command _playVideo;
        private Command _goFader;
        private Command _fadeVideo;
        private Command _flashDialog;
        private string _clipSessionTitle = "";
        private ClipCollection _currentChannel;
        private ClipItem _currentTopic;
        private ClipShowContent _currentLibrary;
        private int _currentShowingVideoIndex = 0;
        private const int NOTIFY_TIMER = 10000; // 10 second notification timer
        private TimeSpan _lastStartPosition;
        private const string SNAG_ALL_TITLE = "All snags";
        private string _flashDialogMessage = "";
        private string _lastTitleValue = "";

        public MainCodeBehind()
        {
            _myChannelSource = new Choice();

            // Instantiate MCML items
            _playVideo = new Command();
            _goFader = new Command();
            _fadeVideo = new Command();
            _flashDialog = new Command();

            // Define command bar items
            #region Command bar definitions
            ArrayListDataSet tempCommandBarItems = new ArrayListDataSet();
            tempCommandBarItems.Add(new CommandBarItem("Full", "view currently playing clip in full screen"));
            tempCommandBarItems.Add(new CommandBarItem("Browse", "browse my media"));
            tempCommandBarItems.Add(new CommandBarItem("Duration", "set current clip playback length"));
            tempCommandBarItems.Add(new CommandBarItem("Shuffle", "shuffle current playlist or clip collection"));
            tempCommandBarItems.Add(new CommandBarItem("Snag", "snag this clip to watch again later"));
            tempCommandBarItems.Add(new CommandBarItem("Linked", "list media items that are linked to this one"));
            tempCommandBarItems.Add(new CommandBarItem("Stop", "end current clip show and close"));

            base.AddCommandBarItems(tempCommandBarItems);
            #endregion


        }

        public TimeSpan DebugInvoke
        {
            set
            {
                Console.WriteLine("{0}", value);
            }
        }

        public ArrayListDataSet BuildChannelAllSnags()
        {
            ArrayListDataSet tempResults = new ArrayListDataSet();
            Storage st = new Storage();
            ClipShowContent csc = st.GetSnagCollection();
            foreach (MediaMetaData clip in csc.MediaItems)
            {
                foreach (SnagItem si in clip.SnagList)
                {
                    MediaMetaData item = clip.Clone();
                    item.Title = String.Format("{0} ({1})", clip.Title, si.SnagName);
                    if (File.Exists(si.ThumbnailUrl))
                    {
                        item.Thumbnail = new Image(BuildImagePath(si.ThumbnailUrl));
                    }
                    else
                    {
                        item.Thumbnail = new Image(BuildImagePath(item.ThumbnailUrl));
                    }
                    item.SnagClipLength = si.ClipLength;
                    item.SnagTimeSpan = si.ItemTimeSpan.ToString(); // si.StartTime;
                    item.IsSnagItem = true;
                    tempResults.Add(item);
                }
            }
            return (tempResults);
        }

        public ArrayListDataSet BuildChannelFromSnags(MediaMetaData parent)
        {
            ArrayListDataSet tempResults = new ArrayListDataSet();
            string parentTitle = parent.Title;
            foreach (SnagItem si in parent.SnagList)
            {
                MediaMetaData item = parent.Clone();
                item.Title = String.Format("{0} ({1})", parentTitle, si.SnagName);
                if (File.Exists(si.ThumbnailUrl))
                {
                    item.Thumbnail = new Image(BuildImagePath(si.ThumbnailUrl));
                }
                else
                {
                    item.Thumbnail = new Image(BuildImagePath(item.ThumbnailUrl));
                }
                item.SnagClipLength = si.ClipLength;
                item.SnagTimeSpan = si.ItemTimeSpan.ToString(); // si.StartTime;
                item.IsSnagItem = true;
                tempResults.Add(item);
            }
            return (tempResults);
        }

        public ArrayListDataSet BuildChannelFromAll(string keyWords, Choice sourceLib)
        {
            ArrayListDataSet tempResults = new ArrayListDataSet();

            foreach (ClipShowContent lib in sourceLib.Options)
            {
                foreach (MediaMetaData item in lib.MediaItems)
                {
                    if (!item.Title.Equals("N/A"))
                    {
                        if (keyWords.Equals("ALL"))
                        {
                            item.Thumbnail = new Image(BuildImagePath(item.ThumbnailUrl));
                            tempResults.Add(item);
                        }
                        else
                        {
                            string[] keywords = keyWords.Split(';');
                            foreach (string keyword in keywords)
                            {
                                if (CheckForKeyword(item, keyword))
                                {
                                    if (!tempResults.Contains(item))
                                    {
                                        item.Thumbnail = new Image(BuildImagePath(item.ThumbnailUrl));
                                        tempResults.Add(item);
                                    }
                                    break;
                                }
                            }
                        }

                    }
                }
            }
            return (tempResults);
        }
        public void ShowFlashMessage(string dialogMessage, bool invokeNow)
        {
            this.FlashMessageText = dialogMessage;
            if (invokeNow)
            {
                _flashDialog.Invoke();
            }
        }

        public ArrayListDataSet BuildChannel(string keyWords, ClipShowContent cm)
        {
            _currentLibrary = cm;
            ArrayList temp = cm.MediaItems;
            ArrayListDataSet tempResults = new ArrayListDataSet();

            foreach (MediaMetaData item in temp)
            {
                if (!item.Title.Equals("N/A"))
                {
                    if (keyWords.Equals("ALL"))
                    {
                        item.Thumbnail = new Image(BuildImagePath(item.ThumbnailUrl));
                        tempResults.Add(item);
                    }
                    else
                    {
                        string[] keywords = keyWords.Split(';');
                        foreach (string keyword in keywords)
                        {
                            if (CheckForKeyword(item, keyword))
                            {
                                if (!tempResults.Contains(item))
                                {
                                    item.Thumbnail = new Image(BuildImagePath(item.ThumbnailUrl));
                                    tempResults.Add(item);
                                }
                                break;
                            }
                        }
                    }

                }
            }
            return (tempResults);
        }


        public void PlayClip()
        {
            try
            {
                if (!File.Exists(this.CurrentUrl))
                {
                    this.ShowFlashMessage(String.Format("Media '{0}' was not found", this.CurrentUrl), true);
                }
                else
                {
                    AddInHost.Current.MediaCenterEnvironment.PlayMedia(Microsoft.MediaCenter.MediaType.Video,
                        this.CurrentUrl, false);
                    if (this.CurrentChannel.PlayClips)
                    {
                        AddInHost.Current.MediaCenterEnvironment.MediaExperience.Transport.Position = this.Skip;
                    }
                }


            }
            catch (SystemException se)
            {
                this.ShowFlashMessage(se.Message, true);
            }
            finally
            {
                _playVideo.Invoke();
            }
        }

        private ArrayListDataSet BuildChannel(ClipCollection sourceChannel, int channelItemIndex)
        {
            Storage st = new Storage();
            ClipItem ci = (ClipItem)sourceChannel.Items[channelItemIndex];
            ClipShowContent cm = st.GetMediaLibrary(sourceChannel.MediaSourceFilePath);
            return (BuildChannel(ci.Keywords, cm));
        }

        private ClipShowContent GetContent(string sourceFilePath)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ClipShowContent));
            FileStream fs = new FileStream(sourceFilePath, FileMode.Open);
            ClipShowContent result = (ClipShowContent)serializer.Deserialize(fs);
            fs.Close();

            return (result);
        }

        private void ChangeClipLength()
        {
            _currentChannel.IncrementClipLength();
            this.ShowFlashMessage(String.Format("Clip play length is {0}", _currentChannel.ClipLength), true);
            base.AppSettings.DefaultClipLength = _currentChannel.ClipLength;
            base.ClipNotification.Invoke();
        }

        #region MCML properties/methods
        public void ChangeTopic(ClipItem newChannel, bool forceReplay, int topicIndex)
        {
            base.VideoMetaData.Options = BuildChannel(newChannel.Keywords, _currentLibrary);
            _currentTopic = newChannel;
            base.CurrentFocusVideoIndex = 0;
            _currentShowingVideoIndex = 0;
            if (forceReplay)
            {
                if (base.AppSettings.UseEffects)
                {
                    _fadeVideo.Invoke();
                }
                PlayClip();
                this.RemoteActivity = true;
            }
        }

        public bool UseEffects
        {
            get { return (base.AppSettings.UseEffects); }
        }

        public bool UseNotification
        {
            get
            {
                if (_currentChannel.PlayClips)
                {
                    return ((_currentChannel.ClipLengthInSeconds - NOTIFY_TIMER) > 0);
                }
                else
                {
                    return (false);
                }
            }
        }

        public int NotifyLength
        {
            get
            {
                if (_currentChannel.PlayClips)
                {
                    return (_currentChannel.ClipLengthInSeconds - NOTIFY_TIMER);
                }
                else
                {
                    MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
                    if (item.Duration.Equals(-1))
                    {
                        return (0);
                    }
                    else
                    {
                        return (item.Duration - NOTIFY_TIMER);
                    }
                }
            }
        }

        public string FlashMessageText
        {
            get
            {
                return (_flashDialogMessage);
            }
            set
            {
                _flashDialogMessage = value;
            }
        }

        public Int32 CurrentLength
        {
            get
            {
                if (_currentChannel.PlayClips)
                {
                    return (_currentChannel.ClipLengthInSeconds);
                }
                else
                {
                    // Return actual length of the clip
                    MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
                    if (item.Duration.Equals(-1))
                    {
                        return(_currentChannel.ClipLengthInSeconds);
                    }
                    else
                    {
                        return (item.Duration);
                    }
                }
            }
        }
        public string CurrentUrl
        {
            get
            {
                MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
                return (item.Url);
            }
        }
        public string CurrentTitle
        {
            get
            {
                MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
                return (base.GetDescriptionText(item, MetadataDescriptor.ItemTitle));
            }
        }
        public string LastTitle
        {
            set
            {
                _lastTitleValue = value;
            }
            get
            {
                return (_lastTitleValue);
            }
        }
        public TimeSpan Skip
        {
            get
            {
                MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
                if (item.IsSnagItem)
                {
                    _currentChannel.ClipLength = item.SnagClipLength;
                    return (TimeSpan.Parse(item.SnagTimeSpan));
                }
                else
                if (_currentChannel.PlayClips)
                {
                    Random r = new Random(unchecked((int)DateTime.Now.Ticks));
                    int minValue = 1;
                    int maxValue = (item.Duration - this.CurrentLength);
                    if (minValue < maxValue)
                    {
                        int offSet = r.Next(minValue, maxValue);
                        TimeSpan ts = new TimeSpan(offSet * 10000);
                        
                        // Store Snag settings in case we need it
                        _lastStartPosition = ts;
                        return (ts);
                    }
                    else
                    {
                        _lastStartPosition = new TimeSpan(0);
                        return (new TimeSpan(0));
                    }
                }
                else
                {
                    _lastStartPosition = new TimeSpan(0);
                    return (new TimeSpan(0));
                }
            }
        }


        public Int32 FadeInterval
        {
            get { return (NOTIFY_TIMER - 1000); }
        }

        public string NextDescription
        {
            get
            {
                int nextCounter = _currentShowingVideoIndex + 1;
                if (nextCounter >= base.VideoMetaData.Options.Count)
                {
                    // Reset to zero
                    nextCounter = 0;
                }
                try
                {
                    MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[nextCounter];
                    return( String.Format("Coming up next:{0}", GetDescriptionText(item, MetadataDescriptor.ItemTitle)));
                }
                catch
                {
                    return( "Description not available");
                }
                finally
                {
                    if (base.AppSettings.UseEffects)
                    {
                        _goFader.Invoke();
                    }
                }
            }
        }

        public string CurrentDescription
        {
            get
            {
                try
                {
                    MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
                    string temp = GetDescriptionText(item, MetadataDescriptor.ItemDescription);
                    if (temp.Equals(GetDescriptionText(item, MetadataDescriptor.ItemTitle)))
                    {
                        return (String.Format("{0}", item.CreationDateTime.ToString("MMMM yyyy")));
                    }
                    else
                    {
                        return (String.Format("{0} ({1})",
                            GetDescriptionText(item, MetadataDescriptor.ItemDescription),
                            item.CreationDateTime.ToString("MMMM yyyy")));
                    }
                }
                catch
                {
                    return ("Description not available");
                }
            }
        }

        public string CurrentChannelTopic
        {
            get
            {
                return(String.Format("{0}-{1}",
                    _currentChannel.Name, _currentTopic.Name));
            }
        }

        public ClipCollection CurrentChannel
        {
            get
            {
                return (_currentChannel);
            }
            set
            {
                _currentChannel = value;
                _currentChannel.ClipLength = base.AppSettings.DefaultClipLength;
            }
        }
        public string ClipSessionTitle
        {
            get { return (_clipSessionTitle); }
            set { _clipSessionTitle = value; }
        }
        public Command PlayMedia
        {
            get
            {
                return(_playVideo);
            }
        }
        public Command FlashMessage
        {
            get
            {
                return (_flashDialog);
            }
        }
        public void ChangeChannel()
        {
            base.StopPlayback();
            ClipCollection channel = (ClipCollection)_myChannelSource.Chosen;
            base.VideoMetaData.Options = BuildChannel(channel, 0);
            base.CurrentFocusVideoIndex = 0;
            _currentShowingVideoIndex = 0;
            _currentChannel = channel;
            _currentChannel.ClipLength = base.AppSettings.DefaultClipLength;
            _currentTopic = (ClipItem)channel.Items[0];
        }

        public void CreateChannel(ClipCollection sourceChannel, Choice sourceItems)
        {
            base.VideoMetaData.Options = sourceItems.Options;
            base.CurrentFocusVideoIndex = 0;
            _currentShowingVideoIndex = 0;
            _currentChannel = sourceChannel;
            _currentChannel.ClipLength = base.AppSettings.DefaultClipLength;
            _currentTopic = (ClipItem)sourceChannel.Items[0];
        }
        public void IncrementIndex()
        {
            try
            {
                _currentShowingVideoIndex++;
                if (_currentShowingVideoIndex >= base.VideoMetaData.Options.Count)
                {
                    // Reset to zero
                    _currentShowingVideoIndex = 0;
                }

                PlayClip();
                //_playVideo.Invoke();
            }
            catch (SystemException se)
            {
                this.ShowFlashMessage(se.Message, true);
            }
        }

        public void FadeAndPlay()
        {
            _currentShowingVideoIndex = base.CurrentFocusVideoIndex;
            PlayClip();
            //_playVideo.Invoke();
            this.RemoteActivity = true;
        }

        public int CurrentViewIndex
        {
            set
            {
                _currentShowingVideoIndex = value;
            }
            get
            {
                return (_currentShowingVideoIndex);
            }
        }

        public Command FaderStart
        {
            get { return (_goFader); }
        }

        public Command FadeVideo
        {
            get { return (_fadeVideo); }
        }

        public void BuildTopics(ClipCollection source)
        {
            ArrayListDataSet tempTopics = new ArrayListDataSet();
            foreach (ClipItem ci in source.Items)
            {
                tempTopics.Add(ci);
            }

            base.ToplineChoices.Options = tempTopics;
            _currentChannel = source;
            _currentChannel.ClipLength = base.AppSettings.DefaultClipLength;
        }


        public void CheckForRemoteActivity()
        {
            if (!this.RemoteActivity)
            {
                if (!this.FlagHidden)
                {
                    this.FlagHidden = true;
                    base.HideSelectionControls.Invoke();
                    this.ShowFlashMessage("Press 'OK' or Enter to toggle menu", false);
                }
            }
            else
            {
                this.RemoteActivity = false;
            }
        }

        public ChannelBuilderCodeBehind BuildRelatedPage()
        {
            MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
            ChannelBuilderCodeBehind cbcb = new ChannelBuilderCodeBehind(item);
            return (cbcb);
        }

        public new void ProcessCommand(int commandIndex)
        {
            try
            {
                // Go full screen
                if (commandIndex == 0)
                {
                    this.FlagHidden = true;
                    base.ShowDialog("clipShow","Press the back button to return to clipShow", true);
                    AddInHost.Current.MediaCenterEnvironment.MediaExperience.GoToFullScreen();
                }

                // Change clip
                if (commandIndex == 2)
                {
                    ChangeClipLength();
                }

                // Shuffle clip collection
                if (commandIndex == 3)
                {
                    ShuffleClips();
                }

                // Snag current playing clip
                if (commandIndex == 4)
                {
                    if (_currentChannel.PlayClips)
                    {
                        Storage st = new Storage();
                        ClipShowContent target = st.GetSnagCollection();

                        MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];

                        
                        bool foundItem = false;
                        foreach (MediaMetaData source in target.MediaItems)
                        {
                            if (!source.Title.Equals(SNAG_ALL_TITLE))
                            {
                                if (source.Url.Equals(item.Url))
                                {
                                    SnagItem si = new SnagItem();
                                    si.SnagName = String.Format("clip #{0}", source.SnagList.Count + 1);
                                    si.ItemTimeSpan = _lastStartPosition.ToString();
                                    si.ClipLength = _currentChannel.ClipLength;
                                    si.ThumbnailUrl = String.Format("{0}\\{1}_{2}.jpg", Path.GetDirectoryName(item.ThumbnailUrl),
                                        Path.GetFileNameWithoutExtension(item.ThumbnailUrl),
                                        si.SnagName);
                                    source.SnagList.Add(si);
                                    foundItem = true;
                                    break;
                                }
                            }
                        }

                        if (!foundItem)
                        {
                            SnagItem si = new SnagItem();
                            si.SnagName = "clip #1";
                            si.ItemTimeSpan = _lastStartPosition.ToString();
                            si.ClipLength = _currentChannel.ClipLength;
                            si.ThumbnailUrl = String.Format("{0}\\{1}_{2}.jpg", Path.GetDirectoryName(item.ThumbnailUrl),
                                Path.GetFileNameWithoutExtension(item.ThumbnailUrl),
                                si.SnagName);
                            item.SnagList.Add(si);
                            target.MediaItems.Add(item);
                        }
                        st.PersistSnagCollection(target);
                        base.ShowDialog("clipShow", "Clip has been snagged.", true);
                    }
                    else
                    {
                        base.ShowDialog("clipShow", "Please change Duration from 'All' to snag this clip.", true);
                    }
                }

                if (commandIndex == 6)
                {
                    // stop video and close application 
                    base.StopPlayback();
                    AddInHost.Current.ApplicationContext.CloseApplication();
                }
            }
            catch(SystemException)
            {
                // Do nothing for now (most likely debugging in MCMLPad)
            }
        }

        public Choice ChannelSources
        {
            get { return (_myChannelSource); }
        }

        internal void FPC(object Val)
        {

            String Value = (String)Val;

            if (Application.IsApplicationThread == true)

                FirePropertyChanged(Value);

            else
            {
                Application.DeferredInvoke(FPC, Value);

            }

        }

        //public void RefreshExperience()
        //{
        //    try
        //    {
        //        AddInHost.Current.MediaCenterEnvironment.MediaExperience.PropertyChanged += new PropertyChangedEventHandler(MediaExperience_PropertyChanged);
        //    }
        //    catch (SystemException se)
        //    {
        //        this.ShowFlashMessage(se.Message, true);
        //        // Do not handle as we are most likely inside MCML environment
        //    }
        //}

        //void MediaExperience_PropertyChanged(object sender,string PropertyChanged)
        //{
        //    this.ShowFlashMessage(String.Format("Fire:{0}",PropertyChanged), true);
        //    System.Diagnostics.EventLog.WriteEntry("clipShow_PropertyChanged", PropertyChanged);
        //    FPC("CheckForEnd");
        //}
        // The MediaTransport.PropertyChanged event was not working properly, so the hack here is to
        // set a five second timer and check for the status of the current Transport
        public void CheckForEnd()
        {
            MediaMetaData item = (MediaMetaData)base.VideoMetaData.Options[_currentShowingVideoIndex];
            if (_currentChannel.PlayClips.Equals(false) || (item.Duration.Equals(-1)))
            {
                try
                {
                    if (AddInHost.Current.MediaCenterEnvironment.MediaExperience.Transport.PlayState.Equals(Microsoft.MediaCenter.PlayState.Finished))
                    {
                        IncrementIndex();
                        return;
                    }

                    if (AddInHost.Current.MediaCenterEnvironment.MediaExperience.Transport.PlayRate.Equals(0))
                    {
                        IncrementIndex();
                        return;
                    }

                    if (AddInHost.Current.MediaCenterEnvironment.MediaExperience.Transport.PlayState.Equals(Microsoft.MediaCenter.PlayState.Stopped))
                    {
                        IncrementIndex();
                        return;
                    }

                }
                catch
                {
                    // Do nothing since we are most likely running in a non-MCE environment
                }
            }
        }
        #endregion
    }
}
